package br.com.spam.pipeline.instruction;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import br.com.spam.pipeline.core.ControlSignal;
import br.com.spam.pipeline.core.Processor;

public abstract class Instruction
{
	protected final Processor processor;

	protected final String op;
	private int index = -1;
	private Map<ControlSignal, Object> controlSignals = new HashMap<ControlSignal, Object>();

	public Instruction(String instruction, Processor processor)
	{
		this.processor = processor;

		String[] instParts = instruction.split(";");
		this.op = instParts[0].substring(0, 6);

		this.generateControlSignals(this.controlSignals);
	}

	public String name()
	{
		return this.getClass().getSimpleName();
	}

	public int index()
	{
		return this.index;
	}

	public void setIndex(int index)
	{
		this.index = index;
	}

	public boolean readRegisters()
	{
		return this.afterInstructionDecode();
	}

	protected boolean afterInstructionDecode()
	{
		return true;
	}

	public boolean instructionFetch()
	{
		return true;
	}

	public boolean instructionDecode()
	{
		return true;
	}

	public boolean execute()
	{
		return true;
	}

	public boolean memory()
	{
		return true;
	}

	public boolean writeBack()
	{
		return true;
	}

	public String getOp()
	{
		return this.op;
	}

	public abstract String getInstructionAsString();

	public final Iterable<Entry<ControlSignal, Object>> getControlSignals()
	{
		return this.controlSignals.entrySet();
	}

	public abstract void generateControlSignals(Map<ControlSignal, Object> controlSignals);

	public void setALUSrcA(ALUSrc aluSrc)
	{
		this.controlSignals.put(ControlSignal.ALUSrcA, aluSrc.ordinal());
	}

	public void setALUSrcB(ALUSrc aluSrc)
	{
		this.controlSignals.put(ControlSignal.ALUSrcB, aluSrc.ordinal());
	}
}
